package chapter_5.demo1;

import chapter_4.Dish;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: hero生仔
 */
public class Solution {
    static List<Dish> menu = Arrays.asList(
            new Dish("pork", false, 800, Dish.Type.MEAT),
            new Dish("beef", false, 700, Dish.Type.MEAT),
            new Dish("chicken", false, 400, Dish.Type.MEAT),
            new Dish("french fries", true, 530, Dish.Type.OTHER),
            new Dish("rice", true, 350, Dish.Type.OTHER),
            new Dish("season fruit", true, 120, Dish.Type.OTHER),
            new Dish("pizza", true, 550, Dish.Type.OTHER),
            new Dish("prawns", false, 300, Dish.Type.FISH),
            new Dish("salmon", false, 450, Dish.Type.FISH));

    public static void main(String[] args) {
//        extracted01();  // 最基本的筛选

//        extracted02();  // 筛选元素后还要去重

//        extracted03();  // 练习题

//        extracted04();

//        extracted05();

//        extracted06();

        extracted07();
    }

    private static void extracted07() {
        // 给定两个数字列表，如何返回所有的数对呢？例如，给定列表[1, 2, 3]和列表[3, 4]，该返回[(1, 3), (1, 4), (2, 3), (2, 4), (3, 3), (3, 4)]。
        ArrayList<Integer> list01 = new ArrayList<>(Arrays.asList(1, 2, 3));
        ArrayList<Integer> list02 = new ArrayList<>(Arrays.asList(3, 4));
//        List<int[]> list = list01.stream()
//                // 其实就是两层 for 循环，但是用map的话会返回一个 Stream<Stream<Integer[]>> --> 所以使用flatMap去扁平化流
//                .flatMap(i -> list02.stream()
//                        .map(j -> new int[]{i, j}))
//                .collect(Collectors.toList());
//
//        List<String> collect = list.stream()
//                .map(Arrays::toString)
//                .collect(Collectors.toList());
//        System.out.println(collect);
        // 如何扩展前一个例子，只返回总和能被3整除的数对呢？例如(2, 4)和(3, 3)是可以的。
        List<int[]> list = list01.stream()
                // 其实就是两层 for 循环，但是用map的话会返回一个 Stream<Stream<Integer[]>> --> 所以使用flatMap去扁平化流
                .flatMap(i -> list02.stream()
                        .filter(j -> (i + j) % 3 == 0)
                        .map(j -> new int[]{i, j}))
                .collect(Collectors.toList());

        List<String> collect = list.stream()
                .map(Arrays::toString)
                .collect(Collectors.toList());
        System.out.println(collect);
    }

    private static void extracted06() {
        // 给定一个数字列表，如何返回一个由每个数的平方构成的列表呢？例如，给定[1, 2, 3, 4, 5]，应该返回[1, 4, 9, 16, 25]。
        ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
        List<Integer> result = list.stream()
                .map(num -> num * num)
                .collect(Collectors.toList());
        System.out.println(result);
    }

    private static void extracted05() {
        // 给定单词列表["Hello","World"]，你想要返回列表["H","e","l", "o","W","r","d"]。
        ArrayList<String> words = new ArrayList<>();
        words.add("Hello");
        words.add("World");
        System.out.println(words);
        List<String> list = words.stream()
                .map(s -> s.split(""))
                // flatMap 方法可以让你把一个流中的每个值都换成另一个流，然后把所有的流连接起来成为一个流
                .flatMap(Arrays::stream)
                .distinct()
                .collect(Collectors.toList());
        System.out.println(list);
    }

    private static void extracted04() {
        // map函数：假如给定一个单词列表，需要返回另一个列表，显示每个单词有几个字母。怎么做？就是利用map，对列表中每个元素应用一个函数。
        // 假如我想知道每道菜的名字有多长
        List<Integer> list = menu.stream()
                .map(dish -> dish.getName().length())
                .collect(Collectors.toList());

        System.out.println(list);
    }

    private static void extracted03() {
        List<Dish> list = menu.stream()
                .filter(dish -> dish.getType() == Dish.Type.OTHER)
                .limit(2)
                .collect(Collectors.toList());
        System.out.println(list);
    }

    private static void extracted02() {
        List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
        numbers.stream()
                .filter(i -> i % 2 == 0)
                .distinct()
                .forEach(System.out::println);
    }

    private static void extracted01() {
        List<Dish> list = menu.stream()
                .filter(Dish::isVegetarian)
                .collect(Collectors.toList());

        System.out.println(list);
    }
}
